<template>
  <div>
    <!-- @closed: 使得再打开 弹出层 的时候，我的频道 显示的是 编辑 状态-->
    <van-popup
      :value="value"
      @input="$emit('input',$event)"
      closeable
      round
      position="bottom"
      :style="{ height: '90%' }"
      close-icon-position="top-left"
      @closed="isEdit=false"
    >
      <!--
    弹出层组件van-popup
    v-model="布尔变量"  设置弹出层是否显示
    现在 通过 :value 和 @input 把v-model给体现出来的，因为具体的控制开关
    @input="$emit('input',$event)" 当前popup允许这样操作，直接传递$event就可以了
    @input="$emit('input')" 当前popup允许这样操作，直接传递$event就可以了
    我们自己设计底层代码，那么 要这样设置 @input="$emit('input',$event.target.value)"

    是要放到父组件的v-model里边的
    现在这个弹出层是否显示的控制模式 与 之前的弹出框的操作完全一致

    closeable 有关闭图标
    round  圆角
    position="bottom" 弹出层是从底部弹出
    :style="{ height: '20%' }"  弹出层高度
    close-icon-position="top-left" 关闭按钮要在左上脚显示
      -->

      <!-- 弹出层页面布局 -->
      <!-- 上面部分 -->
      <div class="channel">
        <div class="channel-head">
          <div>
            <span class="title">我的频道</span>
            <span class="desc">点击进入频道</span>
          </div>
          <div>
            <van-button
              type="danger"
              plain
              size="mini"
              round
              @click="isEdit=!isEdit"
            >{{isEdit?'完成':'编辑'}}</van-button>
          </div>
        </div>
        <!-- van-grid 没有设置column-num属性，默认是4列 -->
        <!-- clickable：是否开启格子点击反馈 true：开启 -->
        <!-- @click="clkChannel(k)":激活被点击的频道，传递其在频道列表数据中的对应的下标 -->
        <van-grid class="channel-content" :gutter="10" clickable>
          <van-grid-item v-for="(item,k) in channelList" :key="item.id" @click="clkChannel(item,k)">
            <span class="text" :style="{color:k===activeChannelIndex?'red':''}">{{item.name}}</span>
            <!-- 删除的叉号按钮图标 class="close-icon"：是下方设置样式的
                 v-show="k>0":使得 推荐 频道，不要设置叉号按钮 ，理论上 推荐 不让删除
                 isEdit: 表示进入编辑状态，才显示叉号按钮
            -->
            <!-- @click="userToRest(item,k)": item:是用户的持久删除(localStorage)  k:是页面级删除  -->
            <van-icon
              v-show="k>0 && isEdit"
              @click="userToRest(item,k)"
              class="close-icon"
              name="close"
            />
          </van-grid-item>
        </van-grid>
      </div>

      <!-- 下面部分 -->
      <div class="channel">
        <div class="channel-head">
          <div>
            <span class="title">频道推荐</span>
            <span class="desc">点击添加频道</span>
          </div>
        </div>
        <van-grid class="channel-content" :gutter="10" clickable>
          <!-- @click:声明事件，使得 推荐频道 的各项被单击后，可以添加到 我的频道 里面去
               同时将 被添加频道 的参数传递过去，item：是参数对象 {id:xxx,name:xxx}
          -->
          <van-grid-item v-for="item in restChannel" :key="item.id" @click="restToUser(item)">
            <div class="info" slot="text">
              <span class="text">{{item.name}}</span>
            </div>
          </van-grid-item>
        </van-grid>
      </div>
    </van-popup>
  </div>
</template>

<script type="text/javascript">
// 导入获取全部频道的api函数
// 导入添加、删除频道的api函数
import { apiChannelAll, apiChannelAdd, apiChannelDel } from '@/api/channel.js'

export default {
  name: 'com-channel',
  data () {
    return {
      // 全部频道数据
      channelAll: [],

      // 我的频道 是否是编辑状态
      isEdit: false // 默认不编辑
    }
  },
  props: {
    // 接收父组件v-model的数据信息
    value: {
      type: Boolean,
      default: false
    },
    // 父传递过来的"我的频道"数据
    channelList: {
      type: Array,
      // 数组的默认值要通过函数function方式设置，可使用箭头函数
      // default:()=>{
      //     return []
      // }
      // 可简写为如下：
      default: () => []
    },
    // 父传递过来的当前激活频道的下标
    activeChannelIndex: {
      type: Number,
      default: 0
    }
  },
  // 计算属性有缓存，相关的data不变化，“结果”会缓存，提示系统性能
  computed: {
    // 获得剩余频道(全部频道-我的频道)
    restChannel () {
      // 1.把‘我的频道’的各个成员的id获取出来，集成一个数组返回[1,5,6,7...]
      // map是映射方法，遍历数组，并以“数组”形式返回修饰后的每个单元信息的信息
      const userChannelIDs = this.channelList.map(item => {
        return item.id
      })

      // 2.对‘全部频道’做过滤，把‘不符合’ 我的频道 的项目收集并返回出来，剩下的就是【剩余频道】
      // 遍历全部频道，返回不在“我的频道”出现的频道
      // filter：对 channelAll 做过滤，把id值不在 userChannelIds 数组中出现的元素通过
      // 新数组给返回出来
      // [{id:33,name:xx},{id:34,name:xx},{id:45,name:xx}…………]
      // Array.includes判断是否包含该元素
      const rest = this.channelAll.filter(item => {
        return !userChannelIDs.includes(item.id)
      })

      // 返回过滤好的 剩余的频道
      return rest
    }
  },
  created () {
    // 获取全部频道数据，做展示
    this.getChannelAll()
  },
  methods: {
    // 1.获取全部频道数据的函数
    async getChannelAll () {
      const result = await apiChannelAll()
      this.channelAll = result.channels
    },

    // 2.添加频道的函数(剩余频道--->我的频道)
    // channel:被添加的频道数据，是对象 {id:xxx,name:xxx}
    //
    restToUser (channel) {
      // 1.对 我的频道 成员属性进行增加，使得发生响应式，以实现页面级增加
      // channelList:是我的频道，是父组件传递过来，子组件通过props接收的，直接进行添加操作就可以
      // 因为父子组件之间，是通过v-model实现的双向绑定的数据，所以子组件的数据做添加了，父组件也会感知到
      // 结论：最后添加好的频道，也会在父组件的页面上实现增加，并显示出来(home/index.vue)
      this.channelList.push(channel)

      // 2.将添加好的频道，存储到localStorage里，做持久添加
      apiChannelAdd(channel)
    },

    // 3.删除频道的处理函数(我的频道--->删除频道)
    // channel: 被删除的频道{id:xxx,name:xxx}
    // index: 被删除频道在 我的频道 列表中的下标序号
    userToRest (channel, index) {
      // 1. 页面级删除，使得有响应式结果，因为父子组件使用了v-model
      // A.我的频道 立即呈现删除效果
      // B.删除的频道 会添加到 剩余频道里面（即：被删除的频道项目 添加到 推荐频道里）
      // C.父组件中(home/index.vue) 也会体现删除效果
      this.channelList.splice(index, 1)

      // 2.localStorage 内存级删除
      apiChannelDel(channel)

      // 判断 删除的如果是最后一个项目，并且其现在还在激活状态，被删除后，就设置前一个项目被激活
      // 判断删除的是最后一个项目，算法：项目删除后的长度 ====  删除下标
      if (
        this.channelList.length === index &&
        this.activeChannelIndex === index
      ) {
        // 算法： activeChannelIndex = index-1
        // activeChannelIndex 是父组件给传递过来的，即子组件要修改父组件传递过来的数据信息，需使用sync/update
        this.$emit('update:activeChannelIndex', index - 1)
      }
    },

    // 4.我的频道，被单击时激活
    clkChannel (channel, index) {
      // 如果此时是 编辑 状态，并且不是推荐项目， 就执行删除操作
      if (this.isEdit && index > 0) {
        // return 停止后续代码执行
        return this.userToRest(channel, index)
      }

      // 关闭弹出层(借助父组件的v-model，使得弹出层关闭)
      this.$emit('input', false)
      // 激活被点击的频道,子组件要修改父组件的成员信息，使用sync/update
      this.$emit('update:activeChannelIndex', index)
    }
  }
}
</script>

<style scoped lang="less" >
.channel {
  margin-top: 70px;
  .channel-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
    .title {
      font-size: 30px;
      margin-right: 5px;
    }
    .desc {
      font-size: 16px;
      color: gray;
    }
  }
  .channel-content {
    .text {
      font-size: 16px;
    }
    .active {
      color: red;
    }
    .close-icon {
      font-size: 20px;
      position: absolute;
      top: -5px;
      right: -5px;
      z-index: 999;
      background-color: #fff;
    }
    .info {
      display: flex;
      align-items: center;
    }
  }
}
</style>
